#include "fileops.h"
#define MAXSTRNUM 6

int TapesLoc[MAXTAPE] = {0};
int lastTape = -1;
int currTape;
int fd = -1;
int errno;

//func_directory_initial_scan

//func_read_curr_tape(buff_size)

/*Reading the Current Tape, buff_size of bytes*/
int read_current_tape(char* buffer, int buff_size) {
    int curPos;
    int status;
    if (fd == -1 || currTape == -1) {
        perror("error no tape loaded\n");
        return 1;
    }

    status = read(fd, buffer, buff_size);

    if (0 > status) {
        perror("error reading tape\n");
        return 1;
    }
    /*updating TapeLoc*/
    curPos = lseek(fd, 0, SEEK_CUR);
    TapesLoc[currTape] = curPos;
    printf("read_current_tape(): read %d bytes - %s\n", status, buffer);
    return status;
}

//func_write_curr_tape(buff)

int write_current_tape(const char* buffer, int size) {
    int status = 0, curPos;
    if (fd == -1 || currTape == -1) {
        perror("error no tape loaded\n");
        return 1;
    }

    status = write(fd, buffer, size);

    if (status < 0) {
        perror("error writing to tape\n");
        return 1;
    }

    /*updating TapeLoc*/
    curPos = lseek(fd, 0, SEEK_CUR);
    TapesLoc[currTape] = curPos;
    printf("write_current_tape(): wrote - %s, status=%d\n", buffer, status);
    return status;
}

//func_create_tape

/*creating a new tape, assuming current tape isn't changed*/
int create_tape() {
    FILE* tempfd;
    char fname[MAXSTRNUM + 4] = "TAPE";
    char stapeNum[MAXSTRNUM];
    char cmd1[6 + MAXSTRNUM + 4];
    char cmd2[8 + 2 * (MAXSTRNUM + 4)];
    sprintf(stapeNum, "%d", lastTape + 1);
    strcat(fname, stapeNum);

    if (lastTape > MAXTAPE) {
        printf("error tape capacity reached\n");
    }
    printf("creating tape..\n");
    tempfd = fopen(fname, "w+");
    if (NULL == tempfd) {
        printf("error creating new tape\n");
        return 1;
    }
    fclose(tempfd);
    tempfd = NULL;

#ifdef ZIPME
    /*zipping the file*/
    if (mybzip(lastTape + 1)) {
        printf("error zipping\n");
        return 1;
    }
#endif

    /*updating TapesLoc*/
    TapesLoc[lastTape + 1] = 0;
    ++lastTape;

    return lastTape;
}


//func_replace_tape (tape_number)

int replace_tape(int tape_num) {
    char fname[MAXSTRNUM + 4] = "TAPE";
    char stapeNum[MAXSTRNUM];
    if (0 > TapesLoc[tape_num]) {
        printf("error replacing to a non existing tape\n");
        return 1;
    }
    sprintf(stapeNum, "%d", tape_num);
    strcat(fname, stapeNum);

    if (fd != -1) {
        printf("Closing fd %d\n", fd);
        close(fd);
        fd = -1;
#ifdef ZIPME
        /*zipping the closing tape */
        if (mybzip(currTape)) {
            printf("error zipping\n");
            return 1;
        }
#endif
        currTape = -1;
    }
#ifdef ZIPME
    /*unzipping the opening tape*/
    if (mybunzip(tape_num)) {
        printf("error unzipping\n");
        return 1;
    }
#endif

    fd = open(fname, O_RDWR);
    printf("fd: %d, tape_num=%d\n", fd, tape_num);
    if (fd == -1) {
        printf("error opening tape number: %d\n", tape_num);
        return 1;
    }
    currTape = tape_num;
    printf("curr_offset = %d\n", TapesLoc[tape_num]);
    lseek(fd, TapesLoc[tape_num], SEEK_SET);
    return 0;
}




//func_rewind_curr_tape

int rewind_current_tape() {
    if (fd == -1 || currTape == -1) {
        perror("error no tape is loaded\n");
        return 1;
    }
    lseek(fd, 0, SEEK_SET);
    TapesLoc[currTape] = 0;
    return 0;
}

//func_delete_tape(tape_number)

int delete_tape(int tape_num) {
    char fname[MAXSTRNUM + 4] = "TAPE";
    char stapeNum[MAXSTRNUM];
    sprintf(stapeNum, "%d", tape_num);
    strcat(fname, stapeNum);
    
    if (tape_num == currTape) {
        close(fd);
        fd = -1;
        currTape = -1;
    }

    if ((tape_num <= lastTape) && (TapesLoc[tape_num] < 0)) {
        perror("error tape was allready deleted\n");
        return 1;
    }
    if (tape_num > lastTape) {
        perror("error there's no such tape\n");
        return 1;
    }
    if (0 != remove(fname)) {
        perror("error deleting tape\n");
        return 1;
    }
    TapesLoc[tape_num] = -1;
    return 0;
}

int mybzip(int tape_num) {
    char cmd1[6 + MAXSTRNUM + 4];
    char cmd2[8 + 2 * (MAXSTRNUM + 4)];
    char fname[MAXSTRNUM + 4];
    sprintf(fname, "TAPE%d", tape_num);

    sprintf(cmd1, "bzip2 %s", fname);
    if (-1 == system(cmd1)) {
        printf("error on zipping");
        return 1;
    }
    sprintf(cmd2, "mv %s.bz2 %s", fname, fname);
    if (-1 == system(cmd2)) {
        printf("error on renaming\n");
        return 1;
    }

    return 0;

}

int mybunzip(int tape_num) {
    char cmd1[8 + 2 * (MAXSTRNUM + 4)];
    char cmd2[12 + MAXSTRNUM + 4];
    char fname[MAXSTRNUM + 4];
    sprintf(fname, "TAPE%d", tape_num);

    sprintf(cmd1, "mv %s %s.bz2", fname, fname);
    if (-1 == system(cmd1)) {
        printf("error on renaming\n");
        return 1;
    }
    sprintf(cmd2, "bunzip2 %s.bz2", fname);
    if (-1 == system(cmd2)) {
        printf("error on unzipping\n");
        return 1;
    }
    return 0;
}

int shutting_down() {
    if (fd != -1) {
        printf("Closing fd %d\n", fd);
        close(fd);
        fd = -1;
#ifdef ZIPME
        /*zipping the closing tape */
        if (mybzip(currTape)) {
            printf("error zipping\n");
            return 1;
        }
#endif
        currTape = -1;
    }
}

//func_directory_initial_scan
//returns -1 for failing , otherwise return the largest index of existing tape

int investigate_tape_lib() {
    DIR *dir = NULL;

    struct dirent * dir_enteries = NULL;
    int i;
    int max_index = -1;
    int suffix = 0;

    //now we assume that we already changed the working dir in main to be the one we want

    if ((dir = opendir(".")) == NULL) {
        printf("directory was open ");
        perror("error opening dir");
        return 1;
    }
    while ((dir_enteries = readdir(dir)) != NULL) {

        if ((0 == strcmp(dir_enteries->d_name, ".")) ||
                (0 == strcmp(dir_enteries->d_name, "..")))
            continue;


        sscanf(dir_enteries->d_name, "TAPE%d", &suffix);
        TapesLoc[suffix] = 1;

        if (suffix >= max_index) {
            max_index = suffix;
        }

    }
    for (i = 0; i <= MAXTAPE; i++) {
        if (TapesLoc[i] == 1)
            printf("%d ", i);
    }
    printf("%d ", max_index);

    lastTape = max_index;

    for (i = 0; i <= max_index; TapesLoc[i++]--);

    return 0;
}


